home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 17
/
CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso
/
CUCD
/
Programming
/
DiceSource
/
src
/
dcpp
/
define.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
14KB
|
601 lines
/*
* (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
* use is allowed under the terms of the DICE-LICENSE FILE,
* DICE-LICENSE.TXT.
*/
/*
* DEFINE.C
*
*/
#include "defs.h"
#ifdef AMIGA
#include "/dc1/tokens.h"
#else
#include "../dc1/tokens.h"
#endif
Prototype void InitDefines(char *);
Prototype void ModifySymbolText(Sym *, short);
Prototype void do_undef(ubyte *, int, long *);
Prototype void do_define(ubyte *, int, long *);
Prototype long PreliminaryReplace(char *, long, char **, short *, short, char **);
Prototype Include * PrepareSymbolArgs(Sym *, ubyte *, long *, long);
Prototype long HandleSymbol(Sym *, ubyte *, long, long);
#define X_LINE (SF_SPECIAL|0x100)
#define X_DATE (SF_SPECIAL|0x200)
#define X_FILE (SF_SPECIAL|0x300)
#define X_BASE_FILE (SF_SPECIAL|0x400)
#define X_TIME (SF_SPECIAL|0x500)
static char SymBaseFileBuf[256];
static char SymFileBuf[256];
static char SymLineBuf[16];
static char SymDateBuf[64];
static char SymTimeBuf[64];
void
InitDefines(master)
char *master;
{
time_t t;
char *ct;
struct tm *tp;
time(&t);
tp = localtime(&t);
ct = ctime(&t);
sprintf(SymBaseFileBuf, "\"%s\"", master);
sprintf(SymDateBuf, "\"%.7s%.4s\"", ct + 4, ct + 20);
sprintf(SymDateBuf + 32, "\"%d.%d.%d\"", tp->tm_mday, tp->tm_mon + 1, tp->tm_year % 100);
sprintf(SymTimeBuf, "\"%.8s\"", ct + 11);
if (StripOpt == 0) {
DefineSimpleSymbol("__LINE__", SymLineBuf, X_LINE);
DefineSimpleSymbol("__DATE__", SymDateBuf, 0);
DefineSimpleSymbol("__TIME__", SymTimeBuf, 0);
DefineSimpleSymbol("__FILE__", SymFileBuf, X_FILE);
DefineSimpleSymbol("__BASE_FILE__", SymBaseFileBuf, 0);
DefineSimpleSymbol("__COMMODORE_DATE__", SymDateBuf + 32, 0);
if (UndefSyms == 0) {
DefineSimpleSymbol("__STDC__", "1", 0);
DefineSimpleSymbol("mc68000", "1", 0);
DefineSimpleSymbol("_DCC", "1", 0);
DefineSimpleSymbol("AMIGA", "1", 0);
}
if (FFPDef)
DefineSimpleSymbol("_FFP_FLOAT","1", 0);
else
DefineSimpleSymbol("_SP_FLOAT", "1", 0);
}
}
void
ModifySymbolText(Sym *sym, short type)
{
Include *inc = GetNominalInclude(0);
switch(type) {
case X_FILE:
if (inc->FileName)
sprintf(SymFileBuf, "\"%s\"", inc->FileName);
else
sprintf(SymFileBuf, "\"<unknown>\"");
sym->TextLen = strlen(sym->Text);
break;
case X_LINE:
sprintf(SymLineBuf, "%ld", inc->LineNo);
sym->TextLen = strlen(SymLineBuf);
break;
}
}
void
do_undef(buf, max, pu)
ubyte *buf;
int max;
long *pu; /* unused */
{
long n = ExtSymbol(buf, 0, max);
if (n)
UndefSymbol(buf, n);
else
cerror(EERROR_UNDEF_NO_SYMBOL);
}
void
do_define(buf, max, pu)
ubyte *buf;
int max;
long *pu; /* unused */
{
int i;
int b;
int symLen;
int numArgs = -1;
char *repBuf;
long repSize;
short alloc = 0;
static char *Args[MAX_ARGS];
static short Lens[MAX_ARGS];
symLen = ExtSymbol(buf, 0, max); /* extract symbol */
b = symLen;
if (b < max && buf[b] == '(') {
numArgs = 0;
++b;
while (b < max && buf[b] != ')') {
while (b < max && WhiteSpace[buf[b]]) /* skip ws */
++b;
i = ExtSymbol(buf, b, max); /* symbol name */
if (i == b) {
cerror(EERROR_ILLEGAL_NULL_SYMBOL);
return;
}
if (numArgs == MAX_ARGS)
cerror(EFATAL_MAX_MACRO_ARGS, MAX_ARGS);
Args[numArgs] = buf + b;
Lens[numArgs] = i - b;
++numArgs;
dbprintf(("Macro Argument: %.*s\n", i -b, buf + b));
b = i;
while (b < max && WhiteSpace[buf[b]])
++b;
if (b >= max || (buf[b] != ')' && buf[b] != ',')) {
cerror(EERROR_EXPECTED_COMMA);
return;
}
if (b < max && buf[b] == ',')
++b;
}
if (b >= max || buf[b] != ')') {
cerror(EERROR_EXPECTED_CLOSE_PAREN);
return;
}
++b;
}
while (b < max && WhiteSpace[buf[b]]) /* skip white space to macro body */
++b;
/*
* Lens and Args are modified, a new buffer and buffer size is returned.
*
* If a simple macro (no arguments), just tell DefineSymbol() to allocate
* a copy of the text buffer (which can go away since we free file buffers)
*/
if (numArgs > 0) {
repSize = PreliminaryReplace(buf + b, max - b, Args, Lens, numArgs, &repBuf);
} else {
repSize = max - b;
repBuf = buf + b;
alloc = 1;
}
/*
* Define the symbol
*/
DefineSymbol(buf, symLen, 0, numArgs, Args, Lens, repBuf, 1, alloc, repSize);
}
/*
* Do argument replace and create identifiers for the macro arguments that are
* not normal symbols. "+%08lx"
*/
#define TS_SIZE 9
long
PreliminaryReplace(
char *src,
long max,
char **args,
short *lens,
short n,
char **pdst
) {
long i;
long di;
long bytes;
short j;
char *dst;
static long XId; /* replacement id. */
static char Tmp[MAX_ARGS][16];
for (j = 0; j < n; ++j)
sprintf(Tmp[j], "\001%08lx", XId + j); /* TS_SIZE */
/*
* pass 1 : find symbols to replace and figure out the size of the new
* buffer.
*/
bytes = max;
for (i = 0; i < max; ) {
ubyte c = src[i];
if ((c < '0' || c > '9') && SymbolChar[c]) {
long l = ExtSymbol(src, i, max);
short len = l - i;
for (j = 0; j < n; ++j) {
if (lens[j] == len && strncmp(args[j], src + i, len) == 0) {
bytes -= len;
bytes += TS_SIZE;
dbprintf(("MATCH %d\n", len));
break;
}
}
i = l;
} else if (c == '\"') {
i = SkipString(src, i + 1, max);
} else if (c == '\'') {
i = SkipSingleSpec(src, i + 1, max);
} else {
++i;
}
}
/*
* pass 2, do replacement
*/
dbprintf(("replace buffer: %ld/%ld\n", max, bytes));
if (bytes < 16)
dst = zalloc(bytes+1); /* efficiency only */
else
dst = malloc(bytes+1); /* +1 necessary? don't think so... */
if (dst == NULL)
ErrorNoMemory();
for (i = di = 0; i < max && di < bytes;) {
ubyte c = src[i];
if ((c < '0' || c > '9') && SymbolChar[c]) {
long l = ExtSymbol(src, i, max);
short len = l - i;
for (j = 0; j < n; ++j) {
if (lens[j] == len && strncmp(args[j], src + i, len) == 0) {
dbprintf(("MATCH %d\n", len));
break;
}
}
if (j == n) { /* not a replace symbol */
movmem(src + i, dst + di, len);
i += len;
di += len;
} else { /* is a replace symbol */
movmem(Tmp[j], dst + di, TS_SIZE);
i += len;
di += TS_SIZE;
dbprintf(("match len %d (%d/%d)\n", len, j, n));
}
} else if (c == '\"') {
long nn = i;
i = SkipString(src, i + 1, max);
movmem(src + nn, dst + di, i - nn);
di += i - nn;
} else if (c == '\'') {
long nn = i;
i = SkipSingleSpec(src, i + 1, max);
movmem(src + nn, dst + di, i - nn);
di += i - nn;
} else {
dst[di++] = c;
++i;
}
}
if (i != max || di != bytes)
cerror(EFATAL_SOFT_ERROR_REPLACE, i, max, di, bytes);
XId += n;
for (j = 0; j < n; ++j) {
lens[j] = TS_SIZE;
args[j] = Tmp[j];
}
*pdst = dst;
return(bytes);
}
Include *PrepareSymbolArgs(sym, base, ip, max)
Sym *sym;
ubyte *base;
long *ip;
long max; /* Set it negative to avoid doing any dumps */
{
short oldType = sym->Type;
Include *push = PushBase;
long i = *ip;
/* long oi = i; ** position in original pushbase (not used) */
long xi = i; /* position in followed pushbase */
short candump = 1;
if (max < 0)
{
max = -max;
candump = 1;
}
if ((sym->Type & SF_SPECIAL) == 0) {
if (sym->Type & SF_RECURSE) {
cerror(EERROR_RECURSIVE_MACRO, sym->SymName);
push->Index = i;
return(NULL);
}
sym->Type |= SF_RECURSE;
}
if (sym->NumArgs >= 0) { /* overload symbol args symbols */
short j;
/* look for '(' */
for (;;) {
while (i < max && WhiteSpace[base[i]])
++i;
if (i >= max || base[i] != '\n')
break;
++PushBase->LineNo;
ForceLineSpec = 1;
++i;
}
while (i >= max) {
push->Index = i;
if (push->IsFile)
cerror(EWARN_MACRO_CROSSES_INCLUDE);
if ((push = push->Next) == NULL) {
cerror(EERROR_UNEXPECTED_EOF_MACRO, sym->SymName);
sym->Type = oldType;
push->Index = i;
return(NULL);
}
xi = i = push->Index;
max = push->MaxIndex;
base = push->Base;
dbprintf(("SKIPBACK %ld/%ld %08lx\n", i, max, (unsigned long)base));
}
/*
* If no open-paren found then not a macro!
*
* #define fubar(a,b) hi!
* ... int fubar;
*
*/
if (base[i] != '(') {
sym->Type = oldType;
if (push)
push->Index = i;
if (candump)
{
Dump(sym->SymName, 0, sym->SymLen);
Dump(base, xi, i);
}
if (push)
push->Index = i;
*ip = PushBase->Index;
return(NULL);
}
++i;
/*
* scan macro arguments. Macro arguments are valid only at the
* very next level, determined by setting
*/
for (j = 0; j < sym->NumArgs; ++j) {
short parens = 0; /* paren level */
long b; /* base of argument */
while (i < max && WhiteSpace[base[i]])
++i;
b = i;
while (i < max) {
short c = base[i];
if (c == ',' && parens == 0)
break;
if (c == '(') {
++parens;
++i;
} else if (c == ')') {
if (parens == 0)
break;
--parens;
++i;
} else if (c == '\"') {
i = SkipString(base, i + 1, max);
} else if (c == '\'') {
i = SkipSingleSpec(base, i + 1, max);
} else if (c == '\n') {
if (push)
++push->LineNo;
ForceLineSpec = 1;
++i;
} else if (c == '/' && base[i+1] == '*') {
i = SkipComment(base, i + 2, max);
} else {
++i;
}
}
dbprintf(("break-out %ld %c\n", i, base[i]));
{
Sym *asym;
asym = DefineSymbol(
sym->Args[j],
sym->ArgsLen[j],
SF_MACROARG,
-1,
NULL, NULL, base + b, 0, 0, i - b
);
asym->Creator = sym;
}
while (push && i >= max) {
if (push->IsFile)
cerror(EWARN_MACRO_CROSSES_INCLUDE);
push->Index = i;
if ((push = push->Next) == NULL)
break;
i = push->Index;
max = push->MaxIndex;
base = push->Base;
}
if (i < max && base[i] == ',') {
++i;
continue;
}
while (push && i >= max) {
push->Index = i;
if ((push = push->Next) == NULL)
break;
i = push->Index;
max = push->MaxIndex;
base = push->Base;
}
if (i >= max || base[i] != ')') {
cerror(EERROR_EXPECTED_COMMA_CLOSE);
break;
}
}
if (j != sym->NumArgs) {
cerror(EERROR_NOT_ENOUGH_ARGS_MACRO, j, sym->NumArgs);
while (--j >= 0)
UndefSymbol(sym->Args[j], sym->ArgsLen[j]);
sym->Type = oldType;
if (push)
push->Index = i;
return(NULL);
}
if (base[i] != ')') {
cerror(EERROR_EXPECTED_CLOSE_PAREN_ARG, sym->SymName);
} else {
++i;
}
}
if (push)
push->Index = i;
*ip = i;
return(push);
}
/*
* Handle special symbol. Replacement stuff has been stripped of comments.
* Must rescan to handle other macros and such.
*
* symbol -> replace-stuff sym->NumArgs < 0
* symbol(args) -> replace-macro sym->NumArgs >= 0
*
* Must understand parenthesis...
*
* NOTE: In scanning a macro if we reach EOF and expect an open paren we
* may go up a cpp level to continue the scan.
*
* #define dec(var) ((var)--)
* #define apply(func) (func(Glob))
* apply(dec);
*
* This can get tricky. Basically, we pull the rug from under
* previous levels of CPP(). Thus, CPP() must be very careful in
* this regard.
*
* #define GAG(a,b) (a,b)
* GAG(GAG(1,2),3)
*
* Theoretically the macro arguments are supposed to be evaulated
* first to allow this type of nesting. But, we evaluate bottom
* up! To make this work right when a lower level macro's args
* are evaulated the higher level macro names must be RE-ENABLED!
*
*
* This routine must return in index relative to the original PushBase
* regardless of any data it pulls from higher level pushbase's
*/
long
HandleSymbol(sym, base, i, max)
Sym *sym;
ubyte *base;
long i;
long max;
{
Include *push;
short oldType = sym->Type;
short creType = 0;
short save_fls;
{
long it = i;
push = PrepareSymbolArgs(sym, base, &it, max);
if (push == NULL) return(it);
}
/*
* If pushing a macro argument for replace we must enable the macro
* it came from. This allows MAX(MAX(1,2),3) while disallowing loop
* conditions, i.e. #define BAR(x) BAR(1,x)
*/
if (sym->Type & SF_MACROARG)
{
if (sym->Creator == NULL)
cerror(EFATAL_SOFTWARE_ERROR_CREATOR);
creType = sym->Creator->Type;
sym->Creator->Type &= ~SF_RECURSE;
}
if (sym->Type & SF_STRINGIZE) {
++GlobalStringize;
fputc('\"', Fo);
}
save_fls = ForceLineSpec;
ForceLineSpec = 0;
PushBase->Index = cpp(PushBase->Index, PushBase->Level + 1,
sym->SymName, NULL, sym->Text, sym->TextLen);
ForceLineSpec = save_fls;
i = push->Index;
if (sym->Type & SF_STRINGIZE) {
--GlobalStringize;
fputc('\"', Fo);
}
if (sym->Type & SF_MACROARG)
sym->Creator->Type = creType;
dbprintf(("(macro-return)"));
if (sym->NumArgs >= 0) { /* undef symbol args symbols */
short j;
for (j = 0; j < sym->NumArgs; ++j) {
if (UndefSymbol(sym->Args[j], sym->ArgsLen[j]) == 0)
cerror(EFATAL_SOFTWARE_ERROR_MACRO, sym->SymName, sym->Args[j]);
}
}
sym->Type = oldType;
push->Index = i;
return(PushBase->Index);
}